/////////////////////////////////////////////////////////////////////////////////////
// Include Files
#include "Main\Game.h"

// main window
#include "Systems\Window.h"

// managers
#include "Managers\MeshManager.h"
#include "Managers\ShaderManager.h"
#include "Managers\TextureManager.h"

// systems
#include "Systems\Options.h"
#include "Systems\Renderer.h"
#include "Systems\Scene.h"

// TODO: scripts instead of objects
#include "Objects\Sky.h"
#include "Objects\Galleon.h"
#include "Objects\Water.h"

/////////////////////////////////////////////////////////////////////////////////////
// ISingleton<CGame> Static Initialization
CGame * ISingleton<CGame>::m_pInstance = CE_NULL;

/////////////////////////////////////////////////////////////////////////////////////
// CGame Implementation

CGame::CGame() { }

CGame::~CGame() { }

void CGame::Initialize()
{
	// create the game window TODO: put this back in Renderer
	m_pWindow->Create();

	// start up managers
	m_pMeshManager->Initialize();
	m_pShaderManager->Initialize();
	m_pTextureManager->Initialize();

	// start up systems
	m_pOptions->Initialize();
	m_pRenderer->Initialize();
	m_pScene->Initialize();

	// start up the game
	string_t strTitle;
	string_t strSceneFile;

	// read the game file
	file_t GameFile;
	if( GameFile.Open(L"..\\Galleons\\Galleons.game", L"r") )
	{
		char_t szLine[32];

		// read the title
		GameFile.ReadLine(szLine, 32);
		strTitle = string_t(szLine);

		// read the scene file name
		GameFile.ReadLine(szLine, 32);
		strSceneFile = L"..\\Galleons\\Scenes\\" + string_t(szLine);

		// close the game file
		GameFile.Close();
	}
	else
	{
		assert(false);
	}

	// read the scene file
	file_t SceneFile;
	if( SceneFile.Open(strSceneFile, L"r") )
	{
		char_t szLine[32];
		int iCount;

		// load meshes
		SceneFile.ReadLine(szLine, 32);
		iCount = _wtoi(szLine);
		for( int i = 0; i < iCount; ++i )
		{
			SceneFile.ReadLine(szLine, 32);
			m_pMeshManager->LoadMeshFile(szLine);
		}

		// load shaders
		SceneFile.ReadLine(szLine, 32);
		iCount = _wtoi(szLine);
		for( int i = 0; i < iCount; ++i )
		{
			SceneFile.ReadLine(szLine, 32);
			m_pShaderManager->LoadShaderFile(szLine);
		}

		// load textures
		SceneFile.ReadLine(szLine, 32);
		iCount = _wtoi(szLine);
		for( int i = 0; i < iCount; ++i )
		{
			SceneFile.ReadLine(szLine, 32);
			m_pTextureManager->LoadTextureFile(szLine);
		}

		// create objects
		SceneFile.ReadLine(szLine, 32);
		iCount = _wtoi(szLine);
		for( int i = 0; i < iCount; ++i )
		{
			SceneFile.ReadLine(szLine, 32);
		}

		// HACK: ignoring file, adding objects here
		m_pScene->AddObject( new CSky() );
		m_pScene->AddObject( new CGalleon() );
		m_pScene->AddObject( new CWater() );

		// close the scene file
		SceneFile.Close();
	}
	else
	{
		assert(false);
	}

	// TODO: this class should most likely receive messages, not events... or are 
	// they event different? maybe there should be broadcast events of some sort?
	AddEventListener( m_pWindow->Close, &CGame::OnWindowClose );
}

void CGame::Shutdown()
{
	// TODO: see above
	RemoveEventListener( m_pWindow->Close, &CGame::OnWindowClose );

	// shut down all systems
	m_pScene->Shutdown();
	m_pRenderer->Shutdown();
	m_pOptions->Shutdown();

	// destroy the main window
	m_pWindow->Destroy();

	// shut down all managers
	m_pTextureManager->Shutdown();
	m_pShaderManager->Shutdown();
	m_pMeshManager->Shutdown();
}

void CGame::Run()
{
	m_bRunning = true;
	while( m_bRunning )
	{
		Sleep( 10 );

		// process game events and messages
		ProcessEvents();
	}
}

void CGame::OnWindowClose( CEventArg &_rArg )
{
	(void)_rArg;

	// stop the loop
	m_bRunning = false;
}
